package com.snatch.snatchnd.service.impl;

import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.snatch.common.utils.PropsLoader;
import com.snatch.common.utils.SystemUtil;
import com.snatch.common.vo.HeartbeatInput;
import com.snatch.common.vo.HeartbeatOutput;
import com.snatch.common.vo.NodeRegisterOutput;
import com.snatch.common.vo.NodeWeb;
import com.snatch.common.vo.RatioDataInput;
import com.snatch.ice.ConnectionParam;
import com.snatch.ice.IceClient;
import com.snatch.snatchmgr.zreocsrvi.NodeManageZreocSrvIPrx;
import com.snatch.snatchmgr.zreocsrvi.NodeManageZreocSrvIPrxHelper;
import com.snatch.snatchnd.constant.SystemConstant;
import com.snatch.snatchnd.system.SystemData;
import com.thoughtworks.xstream.XStream;


@Component
public class NodeIntegration {
	private NodeManageZreocSrvIPrx nodeManageZreocSrvIPrx;
	private IceClient iceClient;
	@Autowired
	private PropsLoader propsLoader;
	private XStream xs = new XStream();
	private Logger logger = Logger.getLogger(NodeIntegration.class);
	

	public void initIceClient() {
		String objKey = propsLoader.props.getProperty("node.nodeManageIce.objKey");
		int count = 0;

		while (true) {
			try {
				iceClient = new IceClient();
				ConnectionParam connParam = new ConnectionParam();
				connParam.setClientCfgClassPath(SystemConstant.ICECONFG_CLIENT);
				connParam.setConnType(ConnectionParam.TCP);
				connParam.setIp(propsLoader.props.getProperty("node.nodeManageIce.ip"));
				connParam.setPort(propsLoader.props.getProperty("node.nodeManageIce.tcpPort"));
				connParam.setTimeOut(Integer.parseInt(propsLoader.props.getProperty("node.nodeManageIce.timeOut")));

				Map<String, Class> prxHelperMap = new HashMap<String, Class>();
				prxHelperMap.put(objKey, NodeManageZreocSrvIPrxHelper.class);

				iceClient.initClientPrxs(connParam, prxHelperMap);
				nodeManageZreocSrvIPrx = (NodeManageZreocSrvIPrx) iceClient.getPrxByKey(objKey);
				logger.info("ICE客户端创建成功");
				break;
			} catch (Exception e) {
				e.printStackTrace();
				if (++count == 1) {
					logger.fatal("抓取节点初始化数据中心的ICE服务端，正在等待节点管理中心启动ICE服务...");
				}
				try {
					Thread.sleep(1000L * 5);
				} catch (Exception e2) {
				}
			}
		}
	}

	/**
	 * 节点注册
	 * 
	 * @param nodeRegisterInput
	 *            节点注册请求报文对象
	 */
	public void nodeRegister(NodeWeb snatchWeb) {
		try {
			// nodeRegisterInput.setIp(SystemUtil.getLocalIP());
			
			String xmlstr = JSON.toJSONString(snatchWeb);
			String reqStr = nodeManageZreocSrvIPrx.nodeRegister(xmlstr);// 响应报文
			NodeRegisterOutput nodeRegisterOutput = JSON.parseObject(reqStr, NodeRegisterOutput.class);

			if (nodeRegisterOutput.getStatus() == 0) {// 失败
				// SystemData.setHasError(true);// 节点注册失败时,设置是否存在错误的标识为true
				logger.info(nodeRegisterOutput.getRemark());// 将失败的原因写入错误日志文件
			}
		} catch (Exception e) {
			logger.error("向管理中心注册当前节点出现异常：" + e.toString() + "，稍后(30s)重试...");
		}
	}

	/**
	 * 心跳
	 * 
	 * @param heartbeatInput
	 *            心跳接口请求报文对象
	 */
	public void heartbeat(HeartbeatInput heartbeatInput) {
		String reqXml = null;
		HeartbeatOutput heartbeatOutput = new HeartbeatOutput();
		try {
			String inputstr = JSON.toJSONString(heartbeatInput);
			String returnXml = nodeManageZreocSrvIPrx.heartbeat(inputstr);
			heartbeatOutput = JSON.parseObject(returnXml,HeartbeatOutput.class);
			if (heartbeatOutput.getStatus() == 0) {// 失败
				logger.info(heartbeatOutput.getRemark());
				this.nodeRegister(SystemData.nodeWebs);
			}
		} catch (Exception e) {
			if (e instanceof Ice.SocketException) {
				synchronized (this.iceClient) {
					logger.error("ICE连接中断，正在试图重连...");
					this.iceClient.setAvailable(false);
					this.initIceClient();
					this.nodeRegister(SystemData.nodeWebs);
					try {
						this.iceClient.wait(1000L);
					} catch (Exception e1) {
						e1.printStackTrace();
					}
				}
				// 重新调用服务
				if (iceClient.isAvailable()) {
					this.nodeRegister(SystemData.nodeWebs);
					nodeManageZreocSrvIPrx.heartbeat(reqXml);
				} else {
					// 记录错误报文日志，不再处理此报文
					logger.error("ICE连接中断，重试失败，放弃本次接口调用，本次要发送的心跳报文为:" + reqXml, e);
				}
			} else if (e instanceof Ice.TimeoutException) {
				logger.error("ICE连接操作超时，放弃本次接口调用，本次要发送的心跳报文为:" + reqXml, e);
			} else {
				logger.error("ICE连接中断，发送其他错误，本次要发送的心跳报文为:" + reqXml, e);
				this.nodeRegister(SystemData.nodeWebs);
			}
			
		}
	}

	/**
	 * 发送抓取数据
	 * 
	 * @param onlyCode
	 * @param ratioDataInput
	 * @return
	 */
	public Long ratioDataInput(RatioDataInput ratioDataInput) {
		String ratiostr = null;
		String retXml = null;
		Long veLong = 0L;
		
		try {
			String version = nodeManageZreocSrvIPrx.versionCode(ratioDataInput.getRatioOnlyCode());
			veLong = Long.valueOf(version);
			/*if(null == version || "".equals(version) || "-1".equals(version)) {
				return -1L;
			}*/
			if(null == ratioDataInput.getVersion() || ratioDataInput.getVersion().compareTo(veLong)>=0){
				ratiostr  = JSON.toJSONString(ratioDataInput);
				// 压缩有效报文
				ratiostr = SystemUtil.gZip(ratiostr);
				StringBuilder sbd = new StringBuilder(ratioDataInput.getRatioOnlyCode()).append(";").append(ratioDataInput.getVersion()).append(";").append(ratiostr);
				retXml = nodeManageZreocSrvIPrx.ratioDataInput(sbd.toString());
				return veLong+1;
			}else{
				return veLong;
			}
			//logger.info(ratioDataInput.getTaskCode()+" 发送数据时间："+(System.currentTimeMillis()-time)+" 数据大小："+ratiostr.length());
			
		} catch (Exception e) {
			if (e instanceof Ice.SocketException) {
				synchronized (this.iceClient) {
					logger.error("ICE连接中断，正在试图重连...");
					this.iceClient.setAvailable(false);
					this.initIceClient();
					this.nodeRegister(SystemData.nodeWebs);
					try {
						this.iceClient.wait(1000L);
					} catch (Exception e1) {
						e1.printStackTrace();
					}
				}
				// 重新调用服务
				if (iceClient.isAvailable()) {
					retXml = nodeManageZreocSrvIPrx.ratioDataInput(ratiostr);
				} else {
					// 记录错误报文日志，不再处理此报文
					logger.error("ICE连接中断，重试失败，放弃本次接口调用，本次要发送的赔率数据报文为:" + ratiostr, e);
				}
			} else if (e instanceof Ice.TimeoutException) {
				logger.error("ICE连接操作超时，放弃本次接口调用，本次要发送的赔率数据报文为:" + ratiostr, e);
			} else {
				logger.error("ICE连接中断，发送其他错误，" , e);
			}
		}
		return 0L;
	}

	/**
	 * 发送盘中信息
	 * 
	 * @param matchInfoDataInput
	 * @return
	 *//*
	public String matchInfoDataInput(MatchInfoDataInput matchInfoDataInput) {
		String thirdSystem = matchInfoDataInput.getThirdSystem();
		
		String sendXml = SystemUtil.createMatchInfoXml(matchInfoDataInput);
		
		SnatchLog.logLive(thirdSystem, sendXml);
		
		// 附加报文前缀(格式:抓取项id;序列码;盘中信息报文)
		StringBuilder sbd = new StringBuilder(thirdSystem + "_" + matchInfoDataInput.getSnatchItem()).append(";").append(matchInfoDataInput.getSeqNum()).append(";").append(sendXml);

		String retXml = null;
		try {
			retXml = nodeManagePrx.matchInfoData(sbd.toString());
		} catch (Exception e) {
			if (e instanceof Ice.SocketException) {
				synchronized (this.iceClient) {
					logger.error("ICE连接中断，正在试图重连...");
					this.iceClient.setAvailable(false);
					this.initIceClient();
					this.nodeRegister(SystemData.nodeConfigs);
					try {
						this.iceClient.wait(1000L);
					} catch (Exception e1) {
						e1.printStackTrace();
					}
				}
				// 重新调用服务
				if (iceClient.isAvailable()) {
					retXml = nodeManagePrx.matchInfoData(sbd.toString());
				} else {
					// 记录错误报文日志，不再处理此报文
					logger.error("ICE连接中断，重试失败，放弃本次接口调用，本次要发送的盘中信息报文为:" + sbd.toString(), e);
				}
			} else if (e instanceof Ice.TimeoutException) {
				logger.error("ICE连接操作超时，放弃本次接口调用，本次要发送的盘中信息报文为:" + sbd.toString(), e);
			} else {
				logger.error("ICE连接中断，发送其他错误，本次要发送的盘中信息报文为:" + sbd.toString(), e);
			}
		}
		
		SnatchLog.logLive(thirdSystem, retXml);

		return retXml;
	}

	*//**
	 * 发送报错信息
	 * 
	 * @param errorInput
	 * @return
	 *//*
	public String error(ErrorInput errorInput) {
		String itemID = SystemUtil.getItemID(errorInput.getThirdSystem(), errorInput.getSnatchItem());

		if (errorInput.isExit()) {// 抓取数据时,登录用户被第三方系统踢出
			LoginThread loginThread = SystemData.loginItemStatus.get(itemID);
			if (null != loginThread) {
				SnatchThread snatchThread = SystemData.snatchItemStatus.get(itemID);
				if (null != snatchThread) {
					snatchThread.destroy();// 销毁该抓取线程
					SystemData.snatchItemStatus.remove(itemID, snatchThread);// 将相应的抓取线程停止
				}
				loginThread.flag = false;// 将登录线程状态置为false
				SystemData.loginItemStatus.remove(itemID, loginThread);// 将相应的登录线程停止
			}
		}

		StringWriter sw = new StringWriter();
		xs.toXML(errorInput, sw);

		String reqXml = sw.toString();
		String respXml = null;
		try {
			respXml = nodeManagePrx.error(reqXml);
		} catch (Exception e) {
			if (e instanceof Ice.SocketException) {
				synchronized (this.iceClient) {
					logger.error("ICE连接中断，正在试图重连...");
					this.iceClient.setAvailable(false);
					this.initIceClient();
					this.nodeRegister(SystemData.nodeConfigs);
					try {
						this.iceClient.wait(1000L);
					} catch (Exception e1) {
						e1.printStackTrace();
					}
				}
				// 重新调用服务
				if (iceClient.isAvailable()) {
					respXml = nodeManagePrx.error(reqXml);
				} else {
					// 记录错误报文日志，不再处理此报文
					logger.error("ICE连接中断，重试失败，放弃本次接口调用，本次要发送的错误信息报文为:" + reqXml, e);
				}
			} else if (e instanceof Ice.TimeoutException) {
				logger.error("ICE连接操作超时，放弃本次接口调用，本次要发送的错误信息报文为:" + reqXml, e);
			} else {
				logger.error("ICE连接中断，发送其他错误，本次要发送的错误信息报文为:" + reqXml, e);
			}
		}
		return respXml;
	}

	*//**
	 * 发送验证码
	 * 
	 * @param validateCodeInput
	 * @return
	 *//*
	public ValidateCodeOutput validateCode(ValidateCodeInput validateCodeInput) {

		StringWriter sw = new StringWriter();
		xs.toXML(validateCodeInput, sw);

		String respStr = null;
		String reqStr = sw.toString();
		try {
			respStr = nodeManagePrx.validateCode(reqStr);
		} catch (Exception e) {
			if (e instanceof Ice.SocketException) {
				synchronized (this.iceClient) {
					logger.error("ICE连接中断，正在试图重连...");
					this.iceClient.setAvailable(false);
					this.initIceClient();
					this.nodeRegister(SystemData.nodeConfigs);
					try {
						this.iceClient.wait(1000L);
					} catch (Exception e1) {
						e1.printStackTrace();
					}
				}
				// 重新调用服务
				if (iceClient.isAvailable()) {
					respStr = nodeManagePrx.validateCode(reqStr);
				} else {
					// 记录错误报文日志，不再处理此报文
					logger.error("ICE连接中断，重试失败，放弃本次接口调用，本次要发送的验证码报文为:" + reqStr, e);
				}
			} else if (e instanceof Ice.TimeoutException) {
				logger.error("ICE连接操作超时，放弃本次接口调用，本次要发送的验证码报文为:" + reqStr, e);
			} else {
				logger.error("ICE连接中断，发送其他错误，本次要发送的验证码报文为:" + reqStr, e);
			}
		}
		
		ValidateCodeOutput validateCodeOutput = new ValidateCodeOutput();

		return (ValidateCodeOutput) xs.fromXML(respStr, validateCodeOutput);
	}
*/
	public PropsLoader getPropsLoader() {
		return propsLoader;
	}

	public void setPropsLoader(PropsLoader propsLoader) {
		this.propsLoader = propsLoader;
	}

	/**
	 * 销毁ICE客户端
	 */
	public void destoryIceClient() {
		iceClient.destoryProxy();
	}

}
